using System;
using System.Xml.Serialization;
using GTA;
using GTA.Native;

namespace CustomPeds;

public class Origin : Script
{
	public DrivingStyle drivingStyle = DrivingStyle.Rushed;

	public bool AutoAttack = true;

	public bool Follow = true;

	public bool Invincible;

	public bool CanWearHelmet = true;

	public int SeatIndex = -1;

	public bool IsTaskDriveToWaypoint;

	[XmlIgnore]
	public Main.Member Member;

	[XmlIgnore]
	public Ped Character;

	public Skin skin = new Skin();

	private static Notification notify1;

	private static Notification notify2;

	// 添加下车动画控制
	private bool isExitingVehicle;
	private DateTime lastTaskCheck = DateTime.MinValue;
	private readonly TimeSpan taskCheckInterval = TimeSpan.FromMilliseconds(500);

	public void BuildPedData(Ped ped, Main.Member member, bool isAddonPed)
	{
		Member = member;
		Character = ped;
		skin = new Skin(ped, isAddonPed);
	}

	public void DetectDriverAndWaypoint()
	{
		if (!Main.IsPedDriverOfCurrentVehicle(Main.P1.Character) && !Main.IsPedDriverOfCurrentVehicle(Main.P2.Character))
		{
			return;
		}
		
		try
		{
			if (!Game.IsWaypointActive)
			{
				Function.Call(Hash._0xE8A25867FBA3B05E, 0, 199, 1f);
				Wait(3000);
			}
			if (Game.IsWaypointActive)
			{
				if (Member == Main.Member.P1)
				{
					Main.P1.TaskDriveToWaypoint();
				}
				else
				{
					Main.P2.TaskDriveToWaypoint();
				}
			}
			else
			{
				UI.Notify(TextSetting.dtw_Notify_NeedWaypoint);
			}
		}
		catch (Exception ex)
		{
			UI.Notify($"检测路点失败: {ex.Message}");
		}
	}

	private void TaskDriveToWaypoint()
	{
		if (IsTaskDriveToWaypoint)
		{
			return; // 防止重复执行
		}
		
		IsTaskDriveToWaypoint = true;
		isExitingVehicle = false;
		
		try
		{
			var waypointPosition = World.GetWaypointPosition();
			var currentVehicle = Main.P1.Character.CurrentVehicle;
			
			if (currentVehicle == null || !currentVehicle.Exists())
			{
				IsTaskDriveToWaypoint = false;
				return;
			}
			
			var speed = Function.Call<float>(Hash._0xF417C2502FFFED43, currentVehicle.Model.Hash);
			
			if (Member == Main.Member.P1)
			{
				// 确保主角为驾驶位、女友为乘客
				Main.EnsureDriverAndPassenger(currentVehicle, Main.P1.Character, (Main.P2.Character != null && Main.P2.Character.IsAlive && Main.P2.Follow) ? Main.P2.Character : null);
				Main.P1.Character.Task.DriveTo(currentVehicle, waypointPosition, 8f, speed, (int)Main.P1.drivingStyle);
				
				// 优化：减少循环频率，添加超时保护
				var startTime = DateTime.Now;
				while (World.CalculateTravelDistance(Main.P1.Character.Position, waypointPosition) >= 10f)
				{
					// 添加超时保护
					if (DateTime.Now.Subtract(startTime).TotalSeconds > 1800) // 30分钟超时
					{
						UI.Notify("驾驶超时，任务结束");
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
					
					OtherHelper.DisplayHelpTextThisFrame($"~INPUT_CONTEXT~ {TextSetting.dtw_HelpText_End}~n~" + $"~INPUT_VEH_ACCELERATE~ {TextSetting.dtw_HelpText_SpeedUp}", loop: true);
					Wait(200); // 减少检查频率
					
					if (Game.IsControlPressed(0, Control.Context))
					{
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
					if (Game.IsControlPressed(0, Control.VehicleAccelerate))
					{
						currentVehicle.ApplyForce(currentVehicle.ForwardVector * 3f);
					}
					if (Game.IsControlPressed(0, Control.ThrowGrenade))
					{
						CleanupNearbyVehicles();
					}
					if (!Main.IsPedDriverOfCurrentVehicle(Main.P1.Character))
					{
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
				}
			}
			
			if (Member == Main.Member.P2)
			{
				// 刚执行女友驾车前往路点命令时，立即执行换座动画
				UI.Notify("开始女友驾车模式，执行换座流程...");
				
				// 1. 主角和女友同时下车
				if (Main.P1.Character != null && Main.P1.Character.IsAlive)
				{
					Main.P1.Character.Task.LeaveVehicle();
				}
				if (Main.P2.Character != null && Main.P2.Character.IsAlive)
				{
					Main.P2.Character.Task.LeaveVehicle();
				}
				
				// 等待下车动画完全完成（增加等待时间确保动画播放完毕）
				Wait(4000);
				
				// 2. 主角走到副驾驶位置
				if (Main.P1.Character != null && Main.P1.Character.IsAlive)
				{
					var passengerSeat = GetFirstAvailablePassengerSeat(currentVehicle);
					if (passengerSeat != VehicleSeat.Any)
					{
						Main.P1.Character.Task.EnterVehicle(currentVehicle, passengerSeat, 5000, 2f, 16);
						Wait(3000); // 等待上车动画完全完成
					}
				}
				
				// 3. 女友走到主驾驶位置
				if (Main.P2.Character != null && Main.P2.Character.IsAlive)
				{
					Main.P2.Character.Task.EnterVehicle(currentVehicle, VehicleSeat.Driver, 5000, 2f, 16);
					Wait(3000); // 等待上车动画完全完成
				}
				
				// 4. 随机选择3个动作之一（移除可能导致瞬移的重复上车动作）
				var random = new Random();
				var actionChoice = random.Next(1, 4); // 1-3
				
				switch (actionChoice)
				{
					case 1:
						// 主角先上车模式（简化，避免重复上车）
						UI.Notify("主角先上车模式");
						// 主角已经在副驾驶位置，无需重复上车
						break;
						
					case 2:
						// 女友先上车模式（简化，避免重复上车）
						UI.Notify("女友先上车模式");
						// 女友已经在主驾驶位置，无需重复上车
						break;
						
					case 3:
						// 同时上车模式（简化，避免重复上车）
						UI.Notify("同时上车模式");
						// 两人已经在正确位置，无需重复上车
						break;
				}
				
				// 5. 换座完成后，开始女友导航
				UI.Notify("换座完成，女友开始导航到目的地...");
				
				// 确保女友在主驾驶位置
				if (!Main.IsPedDriverOfCurrentVehicle(Main.P2.Character))
				{
					UI.Notify("女友未能成功换座到主驾驶位置，任务结束");
					TaskDriveToWaypointEnd(currentVehicle, reach: false);
					return;
				}
				
				Main.P2.Character.Task.DriveTo(currentVehicle, waypointPosition, 8f, speed, (int)Main.P2.drivingStyle);
				
				// 优化：减少循环频率，添加超时保护
				var startTime = DateTime.Now;
				while (World.CalculateTravelDistance(Character.Position, waypointPosition) >= 10f)
				{
					// 添加超时保护
					if (DateTime.Now.Subtract(startTime).TotalSeconds > 1800) // 30分钟超时
					{
						UI.Notify("驾驶超时，任务结束");
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
					
					if (Main.P2.Character.IsDead || !Main.P2.Character.IsAlive)
					{
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
					
					OtherHelper.DisplayHelpTextThisFrame($"~INPUT_CONTEXT~ {TextSetting.dtw_HelpText_End}~n~" + $"~INPUT_VEH_ACCELERATE~ {TextSetting.dtw_HelpText_SpeedUp}", loop: true);
					Wait(200); // 减少检查频率
					
					if (Game.IsControlPressed(0, Control.Context))
					{
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
					if (Game.IsControlPressed(0, Control.VehicleAccelerate))
					{
						currentVehicle.ApplyForce(currentVehicle.ForwardVector * 3f);
					}
					if (Game.IsControlPressed(0, Control.ThrowGrenade))
					{
						CleanupNearbyVehicles();
					}
					if (!Main.IsPedDriverOfCurrentVehicle(Main.P2.Character))
					{
						UI.Notify("女友离开了主驾驶位置，任务结束");
						TaskDriveToWaypointEnd(currentVehicle, reach: false);
						return;
					}
				}
			}
			
			TaskDriveToWaypointEnd(currentVehicle, reach: true);
		}
		catch (Exception ex)
		{
			UI.Notify($"驾驶任务失败: {ex.Message}");
			IsTaskDriveToWaypoint = false;
		}
	}

	private void CleanupNearbyVehicles()
	{
		try
		{
			var nearbyVehicles = World.GetNearbyVehicles(Main.P1.Character, 100f);
			foreach (var vehicle in nearbyVehicles)
			{
				if (vehicle != null && vehicle.Exists() && vehicle.Driver != null && 
					vehicle.Driver != Main.P1.Character && vehicle.Driver != Main.P2.Character)
				{
					vehicle.MarkAsNoLongerNeeded();
					vehicle.Delete();
				}
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "CleanupNearbyVehicles - 清理附近车辆");
		}
	}

	private void TaskDriveToWaypointEnd(Vehicle vehicle, bool reach)
	{
		if (isExitingVehicle)
		{
			return; // 防止重复执行
		}
		
		isExitingVehicle = true;
		IsTaskDriveToWaypoint = false;
		
		try
		{
			Function.Call(Hash._0x8DFCED7A656F8802, true);
			vehicle.Speed = 0f;
			
			// 到达目的地后的简单下车逻辑
			if (Main.P1.Character != null && Main.P1.Character.IsAlive)
			{
				Main.P1.Character.Task.LeaveVehicle();
				Wait(3000); // 等待下车动画完全完成
				Main.P1.Character.Task.ClearAllImmediately();
			}
			
			if (Main.P2.Character != null && Main.P2.Character.IsAlive && Main.P2.Follow)
			{
				Main.P2.Character.Task.LeaveVehicle();
				Wait(3000); // 等待下车动画完全完成
				Main.P2.Character.Task.ClearAllImmediately();
			}
			
			if (reach)
			{
				UI.Notify(TextSetting.dtw_Notify_Reach);
			}
		}
		catch (Exception ex)
		{
			UI.Notify($"结束驾驶任务失败: {ex.Message}");
		}
		finally
		{
			isExitingVehicle = false;
		}
	}

	private VehicleSeat GetFirstAvailablePassengerSeat(Vehicle vehicle)
	{
		try
		{
			if (vehicle == null || !vehicle.Exists())
			{
				return VehicleSeat.Any;
			}
			
			int passengerSeats = vehicle.PassengerSeats;
			for (int i = 0; i < passengerSeats; i++)
			{
				var seat = (VehicleSeat)i;
				if (Main.IsSeatFree(vehicle, seat))
				{
					return seat;
				}
			}
			return VehicleSeat.Any;
		}
		catch
		{
			return VehicleSeat.Any;
		}
	}

	public static string GetPedModelName(Model pedModel)
	{
		try
		{
			return ((PedHash)Convert.ToUInt32(pedModel.ToString(), 16)).ToString();
		}
		catch
		{
			return "Unknown";
		}
	}

	public static void ShowNotify(string _notify1, bool blinking1 = false, string _notify2 = "", bool blinking2 = false)
	{
		try
		{
			if (_notify1 != string.Empty)
			{
				notify1 = UI.Notify(_notify1, blinking1);
			}
			if (_notify2 != string.Empty)
			{
				notify2 = UI.Notify(_notify2, blinking2);
			}
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "ShowNotify - 显示通知");
		}
	}

	public static void NotifyAllClear()
	{
		try
		{
			if (notify1 != null)
			{
				notify1.Hide();
			}
			if (notify2 != null)
			{
				notify2.Hide();
			}
			notify1 = null;
			notify2 = null;
		}
		catch (Exception ex)
		{
			LogHelper.WriteException(ex, "NotifyAllClear - 清除通知");
		}
	}

	public static uint GetHash(string str)
	{
		try
		{
			var num = 0u;
			var array = str.ToLower().ToCharArray();
			for (var i = 0; i < array.Length; i++)
			{
				num += array[i];
				num += num << 10;
				num ^= num >> 6;
			}
			num += num << 3;
			num ^= num >> 11;
			return num + (num << 15);
		}
		catch
		{
			return 0;
		}
	}
}
